<template>
  <div class="editor-header-container">
    <div class="layout-type-container">
      <el-tooltip
        v-for="layout in layoutType"
        :key="layout.value"
        :content="layout.label"
        :open-delay="300"
        :disabled="layout.disable"
        placement="bottom">
        <div class="editor-header-opt-item" @click="widgetAutoLayout(layout.value, layout)">
          <i :class="[layout.disable ? 'icondisable' : '', layout.icon]" class="iconfont font-size-18"></i>
        </div>
      </el-tooltip>
    </div>
    <div class="editor-header-quick flex-justify-start mar-lft-10">
      <div class="font-color-primary font-weight-bold mar-rgt-10">{{widget.name}}</div>
      <!--显示-->
      <div v-if="!widget.isRoot" class="editor-header-opt-item" @click="widgetDisplayCtrl">
        <i :class="!widget.display ? 'icon-Notvisible' : 'icon-browse'"
           class="iconfont font-size-24 cursor-pointer"></i>
      </div>
      <!--锁定-->
      <div v-if="!widget.isRoot" class="editor-header-opt-item" @click="widgetLockCtrl">
        <i :class="widget.isLocked ? 'icon-shangsuo font-color-danger' : 'icon-kaisuo'"
           class="iconfont font-size-18 cursor-pointer"></i>
      </div>
      <!--冻结子组件-->
      <div v-if="showFreezeCtrl" class="editor-header-opt-item" @click="widgetFreezeCtrl">
        <el-tooltip content="冻结子组件" :open-delay="300" placement="bottom">
          <i :class="{'font-color-warning' : widget.isChildrenFreeze}"
             class="iconfont icon-pin font-size-22 cursor-pointer"></i>
        </el-tooltip>
      </div>
      <!--编辑自定义组件-->
      <div v-if="showEditingCtrl" class="editor-header-opt-item" @click="widgetEditingCtrl">
        <el-tooltip content="编辑自定义组件" :open-delay="300" placement="bottom">
          <i :class="{'font-color-primary' : widget.isEditing}"
             class="iconfont icon-editor font-size-22 cursor-pointer"></i>
        </el-tooltip>
      </div>
      <!--分组-->
      <div v-if="selectWidgetIds.length > 1" class="editor-header-opt-item" @click="createGroup(widget)">
        <el-tooltip content="创建分组" :open-delay="300" placement="bottom">
          <i class="iconfont icon-link font-size-22 cursor-pointer"></i>
        </el-tooltip>
      </div>
	    <!--跳转至子页面编辑-->
	    <div v-if="widget.relateSubPage" class="editor-header-opt-item" @click="jumpToSubPage">
		    <el-tooltip content="跳转至子页面编辑" :open-delay="300" placement="bottom">
			    <i class="iconfont icon-resonserate font-size-22 cursor-pointer"></i>
		    </el-tooltip>
	    </div>
      <!--自定义组件尺寸缩放-->
      <el-popover
	      v-model="showScalePopper"
	      width="400"
	      trigger="click"
	      placement="bottom"
	      popper-class="custom-popover">
        <el-tooltip slot="reference" content="组件尺寸缩放" :open-delay="300" placement="bottom">
          <div class="editor-header-opt-item">
            <i class="iconfont icon-scaling font-size-20 cursor-pointer"></i>
          </div>
        </el-tooltip>
        <WidgetScaleControl
	        v-if="showScalePopper"
	        :widget="srcWidget"
	        @scaled="showScalePopper = false"></WidgetScaleControl>
      </el-popover>
    </div>
    <el-popover
      width="450"
      placement="left"
      trigger="hover">
      <div slot="reference" class="editor-header-shortcut font-size-12">
        <span>快捷键</span>
        <i class="el-icon-info"></i>
      </div>
      <div>
        <div>
          <span class="font-weight-bold">删除组件：</span>
          <span class="font-color-primary">Backspace/Delete</span>
        </div>
        <div><span class="font-weight-bold">复制组件：</span><span class="font-color-primary">Ctrl + C</span></div>
        <div>
          <span class="font-weight-bold">粘贴组件：</span>
          <span class="font-color-primary">Ctrl + V</span>，粘贴的组件坐标由鼠标当前点击的位置决定
        </div>
        <div>
          <span class="font-weight-bold">粘贴组件：</span>
          <span class="font-color-primary">Ctrl + Shift + V</span>，粘贴的组件坐标完全和复制的源组件坐标保持一致
        </div>
        <div>
          <span class="font-weight-bold">组件多选：</span>
          按住 <span class="font-color-primary">Shift</span>，进入多选模式，松开即取消多选，
          <!--          同时按住 <span class="font-color-primary">Shift + Alt</span> 可控制多选框的显示和隐藏，便于组件的取消选择，-->
          按下 <span class="font-color-primary">Esc</span> 键即可退出多选模式并清除多选框
        </div>
        <div>
          <span class="font-weight-bold">坐标微调：</span>
          <!--          按住 <span class="font-color-primary">Ctrl</span> 的同时，-->
          按下 <span class="font-color-primary">↑、↓、←、→</span>，即可对组件进行坐标微调
        </div>
        <div>
          <span class="font-weight-bold">单轴移动：</span>
          按住<span class="font-color-primary"> x </span> 或 <span class="font-color-primary"> y </span>，
          可以控制组件只允许 x 轴或 y 轴拖动
        </div>
        <div>
          <span class="font-weight-bold">撤销：</span>
          <span class="font-color-primary">Ctrl + Z</span>
        </div>
        <div>
          <span class="font-weight-bold">重做：</span>
          <span class="font-color-primary">Ctrl + Shift + Z</span>
        </div>
        <div>
          <span class="font-weight-bold">组件锁定：</span>
          <span class="font-color-primary">Ctrl + L</span>，
          <span>lock，锁定与取消锁定组件，同时按住</span>
          <span class="font-color-primary"> Shift</span>，
          <span>则会锁定选中组件的所有子组件</span>
        </div>
        <div>
          <span class="font-weight-bold">创建分组：</span>
          <span class="font-color-primary">Ctrl + G</span>，group，对多选的组件创建分组
        </div>
        <div>
          <span class="font-weight-bold">定位组件：</span>
          <span class="font-color-primary">Shift + F</span>，搜索关联的组件
        </div>
        <div>
          <span class="font-weight-bold">打开小组件：</span>
          <span class="font-color-primary">Ctrl + E</span>，搜索关联的组件
        </div>
        <div class="font-size-12 font-color-warning mar-top-10">注：macOS 中 Command/Win 键等同于 Windows 中的 Ctrl 键
        </div>
      </div>
    </el-popover>
  </div>
</template>

<script>
	import EmptyContent from '@/components/IDE//EmptyContent';
	import CustomColorPicker from '@/components/IDE/colorPicker/Color.vue';
	import ImagePicker from '@/components/IDE/ImagePicker';
	import IconPicker from '@/components/IDE/IconPicker';
	import SizePicker from '@/components/IDE/SizePicker';
	import WidgetScaleControl from "@/components/IDE/WidgetScaleControl.vue";
	import {WidgetClass} from '@/modules/IDE/widget/atom/widget';
	import {WidgetFactory} from '@/modules/IDE/widgetFactory';
	import {mapState} from 'vuex';
	import {deepCopy} from "@/utils";

	export default {
    name: 'EditorHeader',
    components: {
      EmptyContent, ImagePicker, IconPicker, SizePicker, CustomColorPicker, WidgetScaleControl,
    },
    props: {
	    editorType: {
		    type: String,
		    default: 'room', // room/component
	    },
	    srcWidget: {
		    type: WidgetClass,
		    default: () => {
			    return {};
		    }
	    },
    },
    data() {
      return {
	      widget: {},
        layoutType: [
          {
            label: '顶端对齐',
            icon: 'icon-dingbuduiqi',
            value: '7',
            disable: false
          },
          {
            label: '底端对齐',
            icon: 'icon-dibuduiqi',
            value: '8',
            disable: false
          },
          {
            label: '左端对齐',
            icon: 'icon-zuoduiqi',
            value: '9',
            disable: false
          },
          {
            label: '右端对齐',
            icon: 'icon-youduiqi',
            value: '10',
            disable: false
          },
          {
            label: '水平居中',
            icon: 'icon-vertical-center',
            value: '1',
            disable: false
          },
          {
            label: '垂直居中',
            icon: 'icon-horizontal-center',
            value: '2',
            disable: false
          },
          {
            label: '水平等距(子级)',
            icon: 'icon-vertical-equal',
            value: '4',
            disable: false
          },
          {
            label: '垂直等距(子级)',
            icon: 'icon-horizontal-equal',
            value: '3',
            disable: false
          },
          {
            label: '水平等距(父级)',
            icon: 'icon-chuizhidengju',
            value: '5',
            disable: false
          },
          {
            label: '垂直等距(父级)',
            icon: 'icon-shuipingdengju',
            value: '6',
            disable: false
          },
        ],
        locked: false,
        showScalePopper: false,
      };
    },
    computed: {
      ...mapState({
        selectWidgetIds: state => state.ide.selectWidgetIds,
	      selectionBoxRect: state => state.ide.selectionBoxRect,
      }),
      showFreezeCtrl() {
        const {type = '', category = '', children = []} = this.widget;
        if (!children.length) return false;
        if (this.widget.isRoot) return false;
        if (type === 'subPage') return false;
        if (['componentComposite', 'componentDevice'].includes(type)) return false;
        return ['container', 'tabBarPage','pageView'].includes(category);
      },
      showEditingCtrl() {
        if (this.editorType === 'component') return false;
        return ['componentComposite', 'componentDevice','compositeWidget'].includes(this.widget.type);
      },
    },
    watch: {
	    srcWidget: {
		    handler() {
			    this.widget = _.cloneDeep(this.srcWidget);
		    },
		    immediate: true,
	    },
    },
		mounted() {
			this.$EventBus.$on('undoRedoExecute', () => {
				this.widget = _.cloneDeep(this.srcWidget);
			});
		},
		beforeDestroy() {
			this.$EventBus.$off('undoRedoExecute');
		},
    methods: {
      widgetAutoLayout(layout) {
        this.$emit('widgetAutoLayout', false);
        const widgetGroups = {};
        for (let i = 0; i < this.selectWidgetIds.length; i++) {
          const widget = WidgetFactory.getWidgetById(this.selectWidgetIds[i]);
          // 按组件的父级分类
          if (widget.parentId) {
            if (!widgetGroups[widget.parentId]) {
              widgetGroups[widget.parentId] = [widget];
            } else {
              widgetGroups[widget.parentId].push(widget)
            }
          }
        }
        Object.keys(widgetGroups).forEach(widgetId => {
          const parent = WidgetFactory.getWidgetById(widgetId);
          const {width: pWidth = 0, height: pHeight = 0} = parent.rect;
          const children = widgetGroups[widgetId];
          const sum = [];
          switch (layout) {
            case "1":
              //水平居中
              this.autoCenter("1", sum, pWidth, pHeight, children);
              break;
            case "2":
              //垂直居中
              this.autoCenter("2", sum, pWidth, pHeight, children);
              break;
            case "3":
              //垂直等距相对于子级
              this.equidistantElement("3", 'top', parent, children)
              // this.autoEqual("3", sum, pWidth, pHeight, children);
              break;
            case "4":
              //水平等距相对于子级
              this.equidistantElement("4", 'left', parent, children)
              // this.autoEqual("4", sum, pWidth, pHeight, children);
              break;
            case "5":
              //水平等距相对于父级
              this.equidistantLayout("5", 'left', parent, children)
              break;
            case "6":
              //垂直等距相对于父级
              this.equidistantLayout("6", 'top', parent, children)
              break;
            case "7":
              //顶对齐
              this.autoAlignment("7", pHeight, pWidth, children);
              break;
            case "8":
              //底对齐
              this.autoAlignment("8", pHeight, pWidth, children);
              break;
            case "9":
              //左对齐
              this.autoAlignment("9", pHeight, pWidth, children);
              break;
            case "10":
              //右对齐
              this.autoAlignment("10", pHeight, pWidth, children);
              break;
            default:
              break;
          }
        });
        this.$nextTick(() => {
          this.$emit('widgetAutoLayout', true);
        })
      },
      // 水平或垂直 居中
      autoCenter(type, sum, pWidth, pHeight, children) {
        // 方向 1是水平 2是垂直
        const direction = type === "1" ? "top" : "left";
        children = children.sort((a, b) => a.rect[direction] - b.rect[direction]);
        // 改变子组件相对父组件的 top或left 间距

        if (children.length === 1) {
          //单个元素
          for (let i = 0; i < children.length; i++) {
            const child = children[i];
            type === "1"
              ? (child.rect.left = Math.floor((pWidth - child.rect.width) / 2))
              : (child.rect.top = Math.floor((pHeight - child.rect.height) / 2));
          }
        } else {
          //多个元素
          for (let i = 0; i < children.length; i++) {
            const child = children[i];
            type === "1"
              ? (child.rect.left = Math.floor((pWidth - child.rect.width) / 2))
              : (child.rect.top = Math.floor((pHeight - child.rect.height) / 2));
          }
        }
      },
      // 水平或垂直 等分
      autoEqual(type, sum, pWidth, pHeight, children) {
        // 计算子组件等分后的 高度或宽度
        const equal =
          type === "3"
            ? Math.floor(pHeight / children.length)
            : Math.floor(pWidth / children.length);
        // 改变子组件相对父组件的 left或top 间距
        for (let i = 0; i < children.length; i++) {
          const child = children[i];
          type === "3" ? (child.rect.height = equal) : (child.rect.width = equal);
          type === "3"
            ? (child.rect.left = Math.floor((pWidth - child.rect.width) / 2))
            : (child.rect.top = Math.floor((pHeight - child.rect.height) / 2));
          if (i === 0) {
            type === "3" ? (child.rect.top = 0) : (child.rect.left = 0);
          } else {
            type === "3"
              ? (child.rect.top = children[i - 1].rect.top + children[i - 1].rect.height)
              : (child.rect.left = children[i - 1].rect.left + children[i - 1].rect.width);
          }
        }
      },
      // 水平垂直等距相对于子级
      equidistantElement(layout, type, parent, children) {
        const sizeKey = type === 'top' ? 'height' : 'width';
        children = children.sort((a, b) => a.rect[type] - b.rect[type]); // 取出所有子级，并对其排序（当前顺序为选择的顺序，需要还原成原来的顺序）
        const childTotalSize = children.reduce((acc, cur) => acc + cur.rect[sizeKey], 0); // 子元素总宽度或高度
        const firstElement = children[0]
        const lastElement = children[children.length - 1]
        const remainingElements = children.filter((obj) => {
          return ![firstElement.id, lastElement.id].includes(obj.id)
        })
        const remainingCount = remainingElements.length;
        // 计算剩余空间
        const remainingSpace = layout === '5' ? (this.selectionBoxRect.width - childTotalSize) : (this.selectionBoxRect.height - childTotalSize);//得到间隙 减去所有高度 /3
        // 计算垂直间距
        let verticalSpacing = Math.floor(remainingSpace / (remainingCount + 1));
       // console.log(remainingCount, '子元素宽高：', childTotalSize, '总高', this.selectionBoxRect.height, '间隙', verticalSpacing)
        // 计算剩余元素的最终y坐标
        if (layout === '5') {
          //水平等距
          let offset = firstElement.rect.left + firstElement.rect.width + verticalSpacing; // 子元素偏移量
          remainingElements.forEach((child) => {
            child.rect[type] = offset;
            offset += child.rect[sizeKey] + verticalSpacing;
          });
        } else {
          //垂直等距
          if (childTotalSize > this.selectionBoxRect.height) {
            const gap = Math.floor((childTotalSize - this.selectionBoxRect.height) / (children.length - 1));  // 计算每个子元素之间的间距高度
            let offset = this.selectionBoxRect.top + gap; // 子元素偏移量
            remainingElements.forEach(child => {
              child.rect[type] = offset;
              offset += child.rect[sizeKey] - gap;
            })
          } else {
            //总高度大于子元素高度
            let offset = firstElement.rect.top + firstElement.rect.height + verticalSpacing; // 子元素偏移量
            remainingElements.forEach((child, index) => {
              child.rect[type] = offset;
              offset += child.rect[sizeKey] + verticalSpacing;
            });
          }
        }
      },
      //水平垂直等距相对于父级
      equidistantLayout(layout, type, parent, children) {
        const sizeKey = type === 'top' ? 'height' : 'width';
        const parentSize = parent.rect[sizeKey]; // 父级的宽度或高度
        children = children.sort((a, b) => a.rect[type] - b.rect[type]); // 取出所有子级，并对其排序（当前顺序为选择的顺序，需要还原成原来的顺序）
        const childTotalSize = children.reduce((acc, cur) => acc + cur.rect[sizeKey], 0); // 子元素总宽度或高度
        // 子元素总宽度或高度大于父元素宽度或高度
        if (childTotalSize > parentSize) {
          const gap = (childTotalSize - parentSize) / (children.length - 1);  // 计算每个子元素之间的间距高度
          let offset = 0; // 子元素偏移量
          children.forEach(child => {
            child.rect[type] = offset;
            offset += child.rect[sizeKey] - gap;
          })
        } else {
          const gap = (parentSize - childTotalSize) / (children.length + 1);
          let offset = gap;
          children.forEach(child => {
            child.rect[type] = offset;
            offset += child.rect[sizeKey] + gap;
          })
        }
      },
      // 自组件顶对齐
      autoAlignment(type, pHeight, pWidth, children) {
        if (children.length === 1) {
          //单个元素
          if (type === "7") {
            children[0].rect.top = 0;
          } else if (type === "8") {
            children[0].rect.top = pHeight - children[0].rect.height;
          } else if (type === "9") {
            children[0].rect.left = 0;
          } else if (type === "10") {
            children[0].rect.left = pWidth - children[0].rect.width;
          }
        } else {
          //多选元素
          for (let i = 0; i < children.length; i++) {
            const child = children[i];
            if (type === "7") {
              child.rect.top = this.selectionBoxRect.top;
            } else if (type === "8") {
              child.rect.top = (this.selectionBoxRect.height + this.selectionBoxRect.top) - child.rect.height;
            } else if (type === "9") {
              child.rect.left = this.selectionBoxRect.left;
            } else if (type === "10") {
              child.rect.left = (this.selectionBoxRect.width + this.selectionBoxRect.left) - child.rect.width;
            }
          }
        }
      },
      widgetFreezeCtrl() {
	      this.selectWidgetIds.forEach(sid => {
		      const widget = WidgetFactory.getWidgetById(sid);
		      widget.isChildrenFreeze = !this.widget.isChildrenFreeze;
		      WidgetFactory.updateChildrenFreezeStatus(widget, widget.isChildrenFreeze);
	      });
	      this.widget = _.cloneDeep(this.srcWidget);
	      // const operation = (widget) => {
	      // };
	      // this.operationHandler(operation);
      },
      widgetEditingCtrl() {
        this.selectWidgetIds.forEach(sid => {
          const widget = WidgetFactory.getWidgetById(sid);
          widget.isEditing = !this.widget.isEditing;
          WidgetFactory.updateWidgetEditingStatus(widget, widget.isEditing);
        });
	      this.widget = _.cloneDeep(this.srcWidget);
      },
      widgetDisplayCtrl() {
        this.selectWidgetIds.forEach(sid => {
          const widget = WidgetFactory.getWidgetById(sid);
          widget.display = !this.widget.display;
	        // 与组件选择器状态进行同步
	        widget.displayForPicker = widget.display;
        });
	      this.widget = _.cloneDeep(this.srcWidget);
      },
      widgetLockCtrl() {
        this.selectWidgetIds.forEach(sid => {
          const widget = WidgetFactory.getWidgetById(sid);
          WidgetFactory.updateWidgetLockStatus(widget, !this.widget.isLocked);
        });
	      this.widget = _.cloneDeep(this.srcWidget);
      },
	    operationHandler(operation = () => {}) {
		    // 记录组件变更前后的值，用于撤销/重做相关处理
		    const widgetChangeArr = [];
		    this.selectWidgetIds.forEach(widgetId => {
			    const widget = this.getDestWidget(widgetId);
			    if (!widget) return;
			    const oldWidget = WidgetFactory.getWidgetNecessaryProperty(widget);
			    operation(widget);
			    const newWidget = WidgetFactory.getWidgetNecessaryProperty(widget);
			    widgetChangeArr.push({from: oldWidget, to: newWidget});
		    });
		    if (!widgetChangeArr.length) return;
		    WidgetFactory.undoRedoHdl.operationHdl([{operationType: 'edit', widgets: widgetChangeArr}]);
	    },
	    createGroup() {
        this.$emit('createGroup');
      },
	    jumpToSubPage() {
		    this.$EventBus.$emit('jumpToSubPage', this.widget);
	    }
    },
  };
</script>

<style scoped lang="less">
  .editor-header-container {
    height: 50px;
    display: flex;
    justify-content: flex-start;
    align-items: center;
    position: relative;
    border-bottom: 1px solid #DADCE5;

    .editor-header-opt-item {
      text-align: center;
      background: @colorWhite;
      border-radius: 4px;
      margin: 2px;
      cursor: pointer;
    }

    .editor-header-opt-item:hover {
      background: @colorGray95;
    }

    .layout-type-container {
      display: flex;
      justify-content: space-between;
      padding: 5px;

      .editor-header-opt-item {
        width: 36px;
        height: 40px;
        line-height: 40px;
      }

      .icondisable {
        color: #ccc;
      }
    }

    .editor-header-quick {
      font-size: 14px;
      color: @colorGray60;

      .editor-header-opt-item {
        width: 32px;
        height: 32px;
        line-height: 32px;
        font-weight: bold;
      }
    }

    .editor-header-shortcut {
      position: absolute;
      top: 16px;
      right: 30px;
      cursor: pointer;

      &:hover {
        color: @colorPrimary;
      }
    }
  }

</style>
